<template>
    <el-form ref="formRef" :model="formParams" :rules="rules" label-width="auto">
        <aside class="form-title">奖品设置</aside>
        <el-form-item label="奖励方式" prop="reward_type">
            <el-radio-group v-model="formParams.reward_type" class="wrap-radio-group" :disabled="formDisabled">
                <el-radio :label="1">
                    <span>阶梯奖励</span>
                    <span class="form-tip"> 根据完成奖品任务的等级领取对应奖励，可以领取多个奖品 </span>
                </el-radio>
                <el-radio :label="2">
                    <span>单一奖励</span>
                    <span class="form-tip"> 完成多个奖品任务后，用户只可选择已完成中的一个奖品进行领取 </span>
                </el-radio>
            </el-radio-group>
        </el-form-item>
        <el-form-item label="" label-width="0" prop="reward_list">
            <div class="table-tip">
                1）达到奖品任务条件后，奖品库存将被锁定；2）若助力失效，未领取/未核销的奖品库存会释放；3）单一奖励在领取某一个奖品之后，其他奖品库存将释放
            </div>
            <award-settings
                ref="awardSettingsRef"
                :period-type="formParams.period_type"
                :activity-time="formParams.activity_time"
                :form-disabled="formDisabled"
                @submit="handlePrize" />
            <el-table v-if="false" :data="formParams.reward_list" class-name="reward-list">
                <el-table-column label="奖品等级" width="146">
                    <template #header>
                        <formItemLabel label="奖品等级" content="完成任务的奖品等级，最多5级" />
                    </template>
                    <template #default="{ $index }">
                        {{ rewardLevenMap[$index] }}
                    </template>
                </el-table-column>
                <el-table-column prop="reward_title" label="奖品名称" width="122" show-overflow-tooltip />
                <el-table-column prop="reward_image" label="图片" width="78" align="center">
                    <template #default="{ row }: IRewardColumn">
                        <el-image class="reward-image" :src="row.reward_image"></el-image>
                    </template>
                </el-table-column>
                <el-table-column prop="reward_type" label="奖品类型" width="122">
                    <template #default="{ row }: IRewardColumn">
                        {{ renderRewardTypeName(row.reward_type) }}
                    </template>
                </el-table-column>
                <el-table-column prop="reward_stock" label="奖品数量" width="122" />
                <el-table-column prop="help_num" label="助力人数" width="132">
                    <template #header>
                        <formItemLabel label="助力人数" content="用户领取奖品所需要的助力人数" />
                    </template>
                </el-table-column>
                <el-table-column prop="exchange_usage_type" label="兑奖方式" min-width="122">
                    <template #default="{ row }: IRewardColumn">
                        {{ renderExchangeUsageTypeName(row.exchange_usage_type, row) }}
                    </template>
                </el-table-column>
                <el-table-column prop="name" label="操作" width="130" fixed="right">
                    <template #default="{ row, $index }: IRewardColumn">
                        <el-button type="primary" link @click="editReward(row, $index)">编辑</el-button>
                        <el-button v-if="$index > 0 && !pageType?.edit" type="primary" link @click="delReward($index)">
                            删除
                        </el-button>
                    </template>
                </el-table-column>
            </el-table>
            <el-tooltip
                v-if="false"
                :visible="rewardTootipVisible"
                :content="`已达添加上限${MAX_REWARD_LENGTH}个`"
                placement="top-start">
                <div
                    class="button-tooltip-trigger"
                    @mouseenter="handleRewardMouseenter"
                    @mouseleave="handleRewardMouseleave">
                    <el-button
                        type="primary"
                        plain
                        :disabled="formParams.reward_list.length >= MAX_REWARD_LENGTH"
                        @click="openAddReward">
                        <el-icon><Plus /></el-icon>
                        <span>添加奖品</span>
                    </el-button>
                </div>
            </el-tooltip>
        </el-form-item>
        <el-form-item label="奖品领完结束活动" prop="reward_end_switch" class="form-switch-item">
            <el-switch v-model="formParams.reward_end_switch" :active-value="2" :inactive-value="1" />
            <span class="form-tip">开启后，在所有奖品领完之后活动将自动提前结束</span>
        </el-form-item>
        <el-form-item label="是否显示库存" prop="inventory_show_switch" class="form-switch-item">
            <el-switch v-model="formParams.inventory_show_switch" :active-value="2" :inactive-value="1" />
            <span class="form-tip">开启后，将在奖品里显示库存数量，不包含锁定库存</span>
        </el-form-item>
        <aside class="form-title">群聊设置</aside>
        <el-form-item label="选择群聊" prop="groupchat_type" class="form-switch-item">
            <el-radio-group v-model="formParams.groupchat_type" class="wrap-radio-group" :disabled="formDisabled">
                <el-radio :label="1">
                    <span>普通拉群</span>
                    <span class="form-tip"> 选择需要参与活动的群聊，数据每5分钟更新一次 </span>
                </el-radio>
                <el-radio :label="2">
                    <span>无限拉群</span>
                    <span class="form-tip"> 只需要选择一个群聊作为初始群聊，群满可以自动裂变出新的群聊 </span>
                </el-radio>
            </el-radio-group>
        </el-form-item>
        <el-form-item v-show="!isOpen(formParams.groupchat_type)" label="" label-width="0" prop="groupchat_list">
            <el-table
                :data="formParams.groupchat_list"
                row-key="groupchat_id"
                max-height="332px"
                class-name="groupchat-list">
                <el-table-column label="排序" width="106">
                    <template #default="{ $index }">
                        {{ $index + 1 }}
                    </template>
                </el-table-column>
                <el-table-column prop="name" label="群名称" width="276" />
                <el-table-column prop="limit" min-width="200">
                    <template #header>
                        <formItemLabel label="群人数上限" content="因企微限制，自动拉群人数上限为200" />
                    </template>
                    <template #default="{ row }: IGroupColumn">
                        <form-input-number
                            v-model="row.limit"
                            :min="MIN_NUMBER"
                            :max="MAX_GROUP_NUMBER"
                            controls-position="right" />
                    </template>
                </el-table-column>
                <el-table-column prop="name" label="操作" width="198" fixed="right">
                    <template #default="{ $index }: IGroupColumn">
                        <el-button v-if="$index > 0" type="primary" link @click="moveUpGroup($index)"> 上移 </el-button>
                        <el-button
                            v-if="$index < formParams.groupchat_list.length - 1"
                            type="primary"
                            link
                            @click="moveDownGroup($index)">
                            下移
                        </el-button>
                        <el-button type="primary" link @click="delGroup($index)"> 删除 </el-button>
                    </template>
                </el-table-column>
            </el-table>
            <el-tooltip
                :visible="groupTootipVisible"
                :content="`已达添加上限${MAX_GROUP_LENGTH}个`"
                placement="top-start">
                <div
                    class="button-tooltip-trigger"
                    @mouseenter="handleGroupMouseenter"
                    @mouseleave="handleGroupMouseleave">
                    <el-button
                        type="primary"
                        plain
                        :disabled="formParams.groupchat_list.length >= MAX_GROUP_LENGTH"
                        class="add-group-button"
                        @click="openSelectGroup">
                        <el-icon><Plus /></el-icon>
                        <span>添加群聊</span>
                    </el-button>
                </div>
            </el-tooltip>
        </el-form-item>
        <el-form-item v-show="isOpen(formParams.groupchat_type)" label=" " prop="groupchat">
            <el-tooltip :visible="groupSingleTootipVisible" content="已达添加上限1个" placement="top-start">
                <div
                    class="button-tooltip-trigger select-single-button"
                    @mouseenter="handleSingleGroupMouseenter"
                    @mouseleave="handleSingleGroupMouseleave">
                    <el-button
                        type="primary"
                        plain
                        :disabled="Boolean(formParams.groupchat.name)"
                        class="add-group-button"
                        @click="openSelectGroup">
                        <span>选择群聊</span>
                    </el-button>
                </div>
            </el-tooltip>
            <div v-if="formParams.groupchat.name" class="single-group-info">
                <el-image :src="formParams.groupchat.avatar" />
                <div class="zw-text-ellipsis">{{ formParams.groupchat.name }}</div>
                <el-icon size="16" @click="clearGroupchat"><CloseBold /></el-icon>
            </div>
            <div class="form-tip groupchat-tip">
                <div>新群命名示例：</div>
                <div>
                    <p>1）没有数字后缀：初始群名称：裂变群聊 → 新群名称：裂变群聊1、裂变群聊2、...</p>
                    <p>2）有数字后缀：初始群名称：裂变群聊05 → 新群名称：裂变群聊6、裂变群聊7、...</p>
                </div>
            </div>
        </el-form-item>
        <el-form-item
            v-show="!isOpen(formParams.groupchat_type)"
            label="入群顺序"
            prop="join_groupchat_rank"
            class="form-switch-item">
            <el-radio-group v-model="formParams.join_groupchat_rank" :disabled="formDisabled">
                <el-radio :label="1">按顺序入群</el-radio>
                <el-radio :label="2">随机入群</el-radio>
            </el-radio-group>
        </el-form-item>
    </el-form>
    <group-chart ref="groupChartRef" :is-not-name-disabled="true" @submit="handleSubmitGroup" />
    <prize-from-dialog ref="prizeFromDialogRef" @submit="handleSubmitPrize" />
</template>
<script lang="ts" setup>
import { ref, reactive, h, inject, watch, onMounted } from 'vue';
import { FormRules, FormInstance, ElMessageBox } from 'element-plus';
import groupChart from '@/components/chart/GroupChart.vue';

import awardSettings from '@/components/zw/activity/award-settings/index.vue';
import formItemLabel from './form-item-label/form-item-label.vue';
import formInputNumber from './form-input-number/form-input-number.vue';
import prizeFromDialog from './prize-from-dialog/prize-from-dialog.vue';
import { installPrizeCheckRules } from './prize-from-dialog/check-rules';

import { isOpen, MIN_NUMBER, MAX_GROUP_NUMBER, defautlExChangeDate } from '../utils/index';
import { IRewardRow, IRewardColumn, IGroupColumn, IPageType } from '../utils/interface';
import { formParams } from '../utils/paramsManager';
import { get, cloneDeep } from 'lodash';

const pageType: IPageType | undefined = inject('pageType');
/* ---------------------------表单-start---------------------------- */
const formRef = ref<FormInstance>();

/** 进行中、结束的情况下禁用 */
const formDisabled: any = inject('formDisabled');

const awardSettingsRef = ref<any>(null);

onMounted(() => {
    awardSettingsRef.value.setFormParams(formParams);
});
// 校验群聊列表
const checkGroupList = (rule: any, value: any, callback: any) => {
    // 只有普通拉群才校验列表
    if (isOpen(formParams.groupchat_type)) {
        return callback();
    }

    // 校验是否选择
    if (!formParams.groupchat_list.length) {
        return callback(new Error('请添加普通拉群群聊'));
    }

    // 校验是最大数量
    if (formParams.groupchat_list.length > MAX_GROUP_LENGTH) {
        return callback(new Error(`群聊数量不能超过${MAX_GROUP_LENGTH}条`));
    }

    for (const groupItem of formParams.groupchat_list) {
        if (!groupItem.limit) {
            return callback(new Error(`请设置【${groupItem.name}】的群人数上限`));
        }
    }
    callback();
};
// 校验无限拉群选择群
const checkGroupchat = (rule: any, value: any, callback: any) => {
    // 只有无限拉群才校验群聊选择
    if (!isOpen(formParams.groupchat_type)) {
        return callback();
    }

    if (!formParams.groupchat.groupchat_id && formParams.groupchat.groupchat_id !== 0) {
        return callback(new Error(`请选择无限拉群群聊`));
    }

    callback();
};

// 校验奖品列表
const checkRewardList = (rule: any, value: any, callback: any) => {
    // 未有奖励的情况下
    if (!formParams.reward_list.length) {
        return callback(new Error('请添加奖品'));
    }

    // 奖励数量超过的情况下
    if (formParams.reward_list.length > MAX_REWARD_LENGTH) {
        return callback(new Error(`奖品数量不能超过${MAX_GROUP_LENGTH}条`));
    }

    // 依次校验奖励中的字段(优先从最后一个校验, 不然会有校验助力人数不明确的情况)
    for (let index = formParams.reward_list.length - 1; index >= 0; index--) {
        const rewardItem = formParams.reward_list[index];
        const {
            checkStock,
            checkHelpNum,
            checkRequire,
            checkExChangeFileCode,
            checkExChangeDate,
            checkRedEnvelope,
            checkMailInfo
        } = installPrizeCheckRules(rewardItem, Number(index));

        const checkObjFns = [
            () => checkRequire({ message: '请选择奖品类型' }, rewardItem.reward_type), // 校验奖品类型
            () => checkRequire({ message: '请输入奖品名称' }, rewardItem.reward_title), // 校验名称
            () => checkRequire({ message: '请输入奖品图片' }, rewardItem.reward_image), // 校验图片
            checkStock, // 校验库存
            checkHelpNum, // 校验助力人数
            () => checkRequire({ message: '请选择兑奖方式' }, rewardItem.exchange_usage_type), // 校验兑奖方式
            () => checkRequire({ message: '请选择兑奖码方式' }, rewardItem.exchange_code_type), // 校验兑奖码方式
            checkExChangeFileCode, // 校验兑奖码文件
            checkExChangeDate, // 校验兑奖时间
            checkRedEnvelope, // 校验红包金额
            () => checkRequire({ message: '请选择红包类型' }, rewardItem.red_envelope_type), // 校验红包类型
            checkMailInfo, // 校验邮寄信息
            () => checkRequire({ message: '请选择是否更新到客户上' }, rewardItem.is_update) // 校验是否更新字段
        ];

        for (const validator of checkObjFns) {
            const errMessage = validator();
            if (errMessage) {
                return callback(new Error(`【${rewardLevenMap[index]}】${errMessage}`));
            }
        }
    }
    callback();
};

// 校验入群顺序
const checkJoinGroupchatRank = (rule: any, value: any, callback: any) => {
    // 只有普通拉群才校验入群顺序字段是否已经填写
    if (isOpen(formParams.groupchat_type)) {
        return callback();
    }

    if (!value) {
        return callback(new Error('请选择入群顺序'));
    }
    callback();
};
const rules = reactive<FormRules>({
    reward_type: [{ required: true, message: '请选择奖励方式' }],
    groupchat_type: [{ required: true, message: '请选择群聊方式' }],
    groupchat_list: [{ required: true, validator: checkGroupList }],
    groupchat: [{ validator: checkGroupchat }],
    reward_list: [{ validator: checkRewardList }],
    join_groupchat_rank: [{ required: true, validator: checkJoinGroupchatRank }]
});
/**
 * 校验奖品及其群聊表单
 */
const validate = async () => {
    return await formRef.value?.validate();
};
/* ---------------------------表单-end---------------------------- */

/* -----------------------------创建控制tootip显示的工厂-start---------------------------- */
/**
 * @description 创建控制tootip显示的工厂
 * @param maxlength 长度
 * @param list 数组
 * @returns {[tootipVisbleRef, mouseenterFn, mouseleaveFn]}
 */
const tootipFactory = (maxlength: number, listKey: string) => {
    const tootipVisible = ref<boolean>(false);
    /**
     * @description 鼠标移入展示tootip，根据当前是否选中的条数超过最大条
     */
    const mouseenter = () => {
        tootipVisible.value = formParams[listKey].length >= maxlength;
    };
    /**
     * @description 鼠标移入隐藏tootip
     */
    const mouseleave = () => {
        tootipVisible.value = false;
    };

    const ret: Array<any> = [tootipVisible, mouseenter, mouseleave];
    return ret;
};
/* -----------------------------创建控制tootip显示的工厂-end---------------------------- */

/* ----------------------------奖品列表-start---------------------------- */
// 渲染12345级奖品文字
const rewardLevenMap = ['一级奖品', '二级奖品', '三级奖品', '四级奖品', '五级奖品'];

/**
 * @desc 奖品弹窗ref实例化
 */
const prizeFromDialogRef = ref();

/**
 * 根据奖品类型渲染对应的中文
 * @param rewardType 奖品类型
 * @returns {String} '实物奖品'|'红包奖品'
 */
const renderRewardTypeName = function (rewardType: number) {
    const typeMap = {
        1: '实物奖品',
        2: '红包奖品'
    };
    return typeMap[rewardType] ?? '-';
};

/**
 * 根据兑换类型渲染对应的中文
 * @param exchangeUsageType 兑换类型
 * @returns {String} '兑换码'|'线下邮寄'
 */
const renderExchangeUsageTypeName = function (exchangeUsageType: number, rewardRow: IRewardRow) {
    if (rewardRow.reward_type === 2) {
        return '-';
    }
    const typeMap = {
        1: '兑换码',
        2: '线下邮寄'
    };
    return typeMap[exchangeUsageType] ?? '-';
};

/**
 * 编辑奖品列表的数据
 * @param row 奖品数据信息
 */
const editReward = (row: IRewardRow, index: number) => {
    prizeFromDialogRef.value.open(row, index);
};

/**
 * 删除奖品列表的数据
 * @param row 奖品数据信息
 */
const delReward = (index: number) => {
    formParams.reward_list.splice(index, 1);
};

/**
 * 打开添加奖品弹窗
 */
const openAddReward = () => {
    prizeFromDialogRef.value.open();
};

/**
 * 奖品弹窗确认提交
 */
const handleSubmitPrize = (data: IRewardRow, index: number) => {
    // 若是确定的是第一条数据，则停止监听变化
    if (index === 0) {
        unwatchActivityTime?.();
    }
    formParams.reward_list[index] = data;
};

const handlePrize = (data: any) => {
    formParams.reward_list = data;
};

// 奖品tootip
/**
 * @description 最大奖品数量
 */
const MAX_REWARD_LENGTH = 5;

const [rewardTootipVisible, handleRewardMouseenter, handleRewardMouseleave] = tootipFactory(
    MAX_REWARD_LENGTH,
    'reward_list'
);

// 监听活动开始时间的变化，动态设置默认的奖品（第一条是初始数据）的兑换开始结束时间
const unwatchActivityTime = watch(
    () => formParams.activity_time,
    () => {
        if (!pageType?.new) {
            return;
        }
        if (!formParams.activity_time?.length) {
            return;
        }

        if (!formParams.reward_list?.[0]) {
            return;
        }

        const defaultTime = defautlExChangeDate(formParams.period_type, formParams.activity_time);
        formParams.reward_list[0].exchange_time = defaultTime;
    }
);

/* ----------------------------奖品列表-end---------------------------- */

// ----------------------------群聊列表-start---------------------------- */
/**
 * 删除群聊列表的数据
 * @param row 群聊数据信息
 */
const moveUpGroup = (index: number) => {
    if (index === 0) return; // 第一个点击上一步无效操作
    const list = formParams.groupchat_list;
    const upIndex = index - 1;
    [list[index], list[upIndex]] = [list[upIndex], list[index]];
};
/**
 * 删除群聊列表的数据
 * @param row 群聊数据信息
 */
const moveDownGroup = (index: number) => {
    const list = formParams.groupchat_list;
    if (index === list.length - 1) return; // 最后一个点击下一步无效操作

    const downIndex = index + 1;
    [list[index], list[downIndex]] = [list[downIndex], list[index]];
};
/**
 * 删除群聊列表的数据
 * @param row 群聊数据信息
 */
const delGroup = (index: number) => {
    formParams.groupchat_list.splice(index, 1);
};

/**
 * 删除无限拉群时的群聊数据
 */
const clearGroupchat = () => {
    formParams.groupchat = {};
};

/**
 * @description 选择群聊弹窗实例
 */
const groupChartRef = ref<any>();

/**
 * @description 打开选择群聊弹窗
 */
const openSelectGroup = () => {
    formRef.value?.clearValidate(['groupchat_list']);
    let single = false;

    // 无限拉群为单选，否则是多选
    if (formParams.groupchat_type === 2) {
        single = true;
        groupChartRef.value.currentRowReal = formParams.groupchat.groupchat_id; // 回显的idlist
    } else {
        const echoDataId = formParams.groupchat_list.map(item => item.groupchat_id);
        groupChartRef.value.echoDataId = echoDataId; // 回显的idlist
        groupChartRef.value.echoTypeFlag = true;
        groupChartRef.value.echoDataList = cloneDeep(formParams.groupchat_list);
    }
    groupChartRef.value.single = single; // 是否单选
    groupChartRef.value.appDialog.visible = true; // 展示群聊弹窗
};

/**
 * 选择群聊的数据
 */
type IGroupchatData = { name: string; id: number; groupchat_id?: string | number };
/**
 * @description 提交已选择群聊
 */
const handleSubmitGroup = (data: Array<IGroupchatData> | IGroupchatData) => {
    // 多选会返回数组，单选会返回对象，groupchat_type 为 1 时返回数组
    if (Array.isArray(data)) {
        const groupAdapter = data.map(item => {
            return {
                ...item,
                limit: get(
                    formParams.groupchat_list.find(groupItem => groupItem.groupchat_id === item.id),
                    'limit',
                    200
                ),
                groupchat_id: item.id
            };
        });
        formParams.groupchat_list.splice(0);
        formParams.groupchat_list.push(...groupAdapter);
    } else {
        data.groupchat_id = data.id;
        formParams.groupchat.groupchat_id = data.id;
        Object.assign(formParams.groupchat, data);
    }
};

// 群聊tootip
/**
 * @description 普通拉群最大群聊数量
 */
const MAX_GROUP_LENGTH = 30;

const [groupTootipVisible, handleGroupMouseenter, handleGroupMouseleave] = tootipFactory(
    MAX_GROUP_LENGTH,
    'groupchat_list'
);

// 无限拉群tootip
/**
 * @description 无限拉群最大群聊
 */
const groupSingleTootipVisible = ref<boolean>(false);
/**
 * @description 无限拉群移入展示tootip
 */
const handleSingleGroupMouseenter = () => {
    groupSingleTootipVisible.value = Boolean(formParams.groupchat.name);
};
/**
 * @description 无限拉群移s出隐藏tootip
 */
const handleSingleGroupMouseleave = () => {
    groupSingleTootipVisible.value = false;
};
/* ----------------------------群聊列表-end---------------------------- */

defineExpose({
    validate
});
</script>
